package com.ebocy.hammer.core.socket.codecFilter;

import org.apache.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import com.ebocy.hammer.core.log.EbocyLogManager;
import com.ebocy.hammer.core.message.MessageConstants;

public class PackageDecoder implements ProtocolDecoder {
	Logger systemLogger = EbocyLogManager.getSystemLogger();
	
	private static final AttributeKey LAST_DATA = new AttributeKey(
			PackageDecoder.class, "lastData");
	private static final AttributeKey LAST_TIME = new AttributeKey(
			PackageDecoder.class, "lastTime");

	@Override
	public void decode(IoSession iosession, IoBuffer in,
			ProtocolDecoderOutput out) throws Exception {
		Long lastTime = (Long)iosession.getAttribute(LAST_TIME);
		if (lastTime == null) {
			lastTime = 0l;
		}

		long currentTimeMillis = System.currentTimeMillis();
		systemLogger.info("This sission [ " + iosession.getId() + " ] cost time: " + (currentTimeMillis - lastTime));
		iosession.setAttribute(LAST_TIME, currentTimeMillis);

		try {
			IoBuffer oneTimesBuffer = null;
			byte[] lastTimesReaminData = (byte[]) iosession.getAttribute(LAST_DATA);

			if (lastTimesReaminData == null) {
				oneTimesBuffer = in;
				systemLogger.info("=================================in data start=================================================");
				systemLogger.info(oneTimesBuffer.getHexDump());
				systemLogger.info("=================================in data end=================================================");
			} else {
				systemLogger.info("----------------------------------last data start------------------------------------------------");
				systemLogger.info(IoBuffer.wrap(lastTimesReaminData).getHexDump());
				systemLogger.info("----------------------------------last data end------------------------------------------------");
				
				systemLogger.info("================================= at last in data start=================================================");
				systemLogger.info(in.getHexDump());
				systemLogger.info("================================= at last in data end=================================================");

				oneTimesBuffer = IoBuffer.allocate(lastTimesReaminData.length + in.remaining());
				oneTimesBuffer.put(in);
				oneTimesBuffer.put(lastTimesReaminData);
				
				oneTimesBuffer.flip();
				iosession.setAttribute(LAST_DATA, null);
			}

			systemLogger.info("=================================whole data start=================================================");
			systemLogger.info(oneTimesBuffer.getHexDump());
			systemLogger.info("=================================whole data end=================================================");

			byte[] unReadBytes = null;
			boolean messageComplete = true;
			while(messageComplete) {	// 如果单条消息是完整的
				if (oneTimesBuffer.remaining() > MessageConstants.MSG_HEADER_LEN) {
					int messageLength = oneTimesBuffer.getInt();
					if (messageLength <= 6 || messageLength > 5120)
						systemLogger.info("----------------over max length--------------------");
					
					int oneMessageCapcity = messageLength - MessageConstants.MSG_HEADER_LEN;
					if (oneMessageCapcity > 0 && oneTimesBuffer.remaining() >= oneMessageCapcity) {	// 本条消息完整
						byte[] bytes = new byte[oneMessageCapcity];
						oneTimesBuffer.get(bytes);
						IoBuffer buffer = IoBuffer.wrap(bytes);
						out.write(buffer);

//						systemLogger.info("解包循环，当前第"+i+"轮: "+System.currentTimeMillis());
//						printBuffer(buffer);
					} else {	// 本条消息不完整，将本条消息放到下次读取
						messageComplete = false;
						unReadBytes = new byte[MessageConstants.MSG_HEADER_LEN + oneTimesBuffer.remaining()];
						oneTimesBuffer.position(oneTimesBuffer.position() - 4);
						oneTimesBuffer.get(unReadBytes);

						systemLogger.info("本轮数据不完整（一）: "+System.currentTimeMillis());
						systemLogger.info(IoBuffer.wrap(unReadBytes).getHexDump());
					}
				} else {
					// 如果剩余数为0，表示本轮循环消息全部读取，没有不完整的消息
					if (oneTimesBuffer.remaining() == 0)
						break;

					messageComplete = false;
					unReadBytes = new byte[oneTimesBuffer.remaining()];
					oneTimesBuffer.get(unReadBytes);

					systemLogger.info("本轮数据不完整（二）: "+System.currentTimeMillis());
					systemLogger.info(IoBuffer.wrap(unReadBytes).getHexDump());
				}
			}

			// 本轮有消息未读完，放入session供下次读取
			if (!messageComplete && unReadBytes.length > 0) {
				iosession.setAttribute(LAST_DATA, unReadBytes);
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
	}

	private void printBuffer(IoBuffer oneTimesBuffer) {
//		if (true)
//			return;
		if (oneTimesBuffer == null)
			return;
		System.out.println(oneTimesBuffer.getHexDump());
/*
		int i = 0;
		while (oneTimesBuffer.remaining() > 10) {
			byte[] bytes = new byte[10];
			oneTimesBuffer.get(bytes);
			i++;
			System.out.println("line " + i + ": " + IoBuffer.wrap(bytes));
		}
		byte[] bytes = new byte[oneTimesBuffer.remaining()];
		oneTimesBuffer.get(bytes);
		i++;
		System.out.println("line " + i + ": " + IoBuffer.wrap(bytes));
		oneTimesBuffer.flip();
*/
	}

	@Override
	public void finishDecode(IoSession session, ProtocolDecoderOutput out)
			throws Exception {

	}

	@Override
	public void dispose(IoSession session) throws Exception {
	}
}
